package single_game.logic.race_simulator;

import java.util.ArrayList;
import single_game.logic.race_simulator.race_team.RaceRider;
import data.Cyclist;
import main.CyclingManager;

public class RaceSimulator {
	
	public static int seq,	
					  energyBoundPuls = 166,
					  relayChange = 40; 
	public static ArrayList<Cyclist> cyclists = CyclingManager.getInstance().cyclists;
	public static double pulsFactor = 0.03,
						 energyMinimum = 0.2,
						 maximumSpaceBetweenGroups = 0.1,
						 energyMaximum = 100.0;
	public static ArrayList<Group> groups;
	public static ArrayList<RaceRider> stayedBehind;
	
	public RaceSimulator(ArrayList<RaceRider> ridersInGroup) {
		groups = new ArrayList<Group>();
		groups.add(new Group(100, ridersInGroup));
	}
	
	
	public void ride() {
		stayedBehind = new ArrayList<RaceRider>();
		for (int i = 0; i < groups.size(); i++) {		
			Group actualGroup = groups.get(i);
			if (seq % relayChange == 0)											 //Change relay rider 
				actualGroup.changeRelay();
		
			int pace = (int)actualGroup.setPace();                            //Set pace of group			
			
			for (int k = 0; k < actualGroup.relayGroup.size(); k++) {
				RaceRider actual = actualGroup.relayGroup.get(k);
				RaceSimulatorOperations.setParameters(actual, actualGroup, pace, true);
				
			}		
			
			for (int j = 0; j < actualGroup.riders.size(); j++) {
				RaceRider actual = actualGroup.riders.get(j);
				RaceSimulatorOperations.setParameters(actual, actualGroup, pace, false);
			}
			
			groups.get(i).driven += groups.get(i).speed/240.0;			
		}	
		seq++;
		
		makeNewStayedGroups();
		checkGroupsConnection();
	}
	/*
	
	private void printActual() {
		for (int i = 0; i < groups.size(); i++) {
			for (int j = 0; j < groups.get(i).relayGroup.size(); j++)
				System.out.println("Group: "+i+" id:  relay -> "+j+" "+ cyclists.get(groups.get(i).relayGroup.get(j).getCyclistId()).getSurname());
			
			for (int j = 0; j < groups.get(i).riders.size(); j++)
					System.out.println("Group: "+i+" id: "+j+" "+ cyclists.get(groups.get(i).riders.get(j).getCyclistId()).getSurname());
		}
	}
	
	private void actualGroups() {
		for (int i = 0; i < groups.size(); i++) {
			RaceRider rider2;
			if (groups.get(i).relayGroup.size() > 0)
				rider2 = groups.get(i).relayGroup.get(0);
			else
				rider2 = groups.get(i).riders.get(0);
			
			System.out.println((double)rider2.getPower()*(double)(cyclists.get(rider2.getCyclistId()).getMountain()/60)+
					" Id: "+groups.get(i).groupId+" driven: "+groups.get(i).driven+" first "+cyclists.get(rider2.getCyclistId()).getSurname()+" mo: "+
					cyclists.get(rider2.getCyclistId()).getMountain()+" power "+ rider2.getPower()+" action: "+rider2.getAction()+" group members: "
					+(groups.get(i).riders.size()+groups.get(i).relayGroup.size()));
		}
	}
	*/
	
	private void checkGroupsConnection() {		
		for (int i = 0; i < groups.size() - 1; i++) {
			if (groups.get(i).speed < groups.get(i + 1).speed && groups.get(i).driven < groups.get(i + 1).driven+maximumSpaceBetweenGroups) {
				System.out.println("Spawamy: "+i+" "+groups.get(i).driven+" i "+" "+(i+1)+" "+groups.get(i+1).driven);
				weldTwoGroups(i, i + 1);
			}
		}		
	}
	
	//Weld two groups into one
	private void weldTwoGroups(int first, int second) {
		
		for (RaceRider rider: groups.get(second).relayGroup) {
			groups.get(first).addRider(rider);
			groups.get(first).addToRelayGroup(rider);
			rider.setAction("Relay Queue");
		}
		
		for (RaceRider rider: groups.get(second).riders) {
			groups.get(first).addRider(rider);
		}
		pushRightGroups(groups.get(second).groupId);
		groups.remove(groups.get(second));		
	}
	
	
	private void makeNewStayedGroups() {
		for (int i = 0; i < stayedBehind.size(); i++) {
			int previousGroupId = stayedBehind.get(i).getGroupId();
			Group group = findGroupById(previousGroupId);
			if (group.riders.size() > 1) {
				ArrayList<RaceRider> riders = new ArrayList<RaceRider>();
				riders.add(stayedBehind.get(i));
				group.removeRider(stayedBehind.get(i));
				for (int j = i + 1; j < stayedBehind.size(); j++) {
					if (stayedBehind.get(j).getGroupId() == previousGroupId) {
						riders.add(stayedBehind.get(j));
						group.removeRider(stayedBehind.get(j));
						i = j;
					}
					else
						break;
				}
				
				pushLeftGroups(previousGroupId + 1);
				groups.add(previousGroupId - 99, new Group(previousGroupId + 1, riders));
				groups.get(previousGroupId - 99).driven = groups.get(previousGroupId - 100).driven;
				
				if (findGroupById(previousGroupId).riders.size() == 0) {
					groups.remove(findGroupById(previousGroupId));
					pushRightGroups(previousGroupId);
				}				
			}			
		}
	}
	
	public static Group findGroupById(int previousId) {
		Group group = null;
		for (int i = 0; i < groups.size(); i++) {
			if(groups.get(i).groupId == previousId) {
				group = groups.get(i);
				break;
			}
		}
		return group;
	}
	
	private void pushLeftGroups(int id) {
		for (int i = 0; i < groups.size(); i++) {
			if (id <= groups.get(i).groupId) {
				groups.get(i).setGroupId(groups.get(i).groupId + 1);
			}
		}
	}
	
	private void pushRightGroups(int id) {
		for (int i = 0; i < groups.size(); i++) {
			if (id < groups.get(i).groupId) {
				groups.get(i).setGroupId(groups.get(i).groupId - 1);
			}		
		}
	}
}
